package org.fjsei.yewu.controller;

import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.fjsei.yewu.config.MinioConfig;
import org.fjsei.yewu.exception.FileStorageException;
import org.fjsei.yewu.payload.UploadFileResponse;
import org.fjsei.yewu.resolver.TusFileUploadResolver;
import org.fjsei.yewu.service.FileStorageService;
import org.fjsei.yewu.util.MinioUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

//@等删除
//【关键】因graphQL不能正式支持文件上传multipart功能！所以走rest接口。
//@Api(tags = "文件相关接口")     @RequestMapping(value = "product/file")
@Deprecated         //废弃，改成TUS协议+minIO上传的。
@Slf4j
@RestController
@RequestMapping(value = "api")
public class FileController {
    private static final Logger logger = LoggerFactory.getLogger(FileController.class);

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private MinioUtil minioUtil;
    @Autowired
    private MinioConfig prop;

    @jakarta.annotation.Resource
    private TusFileUploadResolver tusFileUploadResolver;

//    @RequestMapping(value = {"/", "/**"}, method = {RequestMethod.POST, RequestMethod.PATCH, RequestMethod.HEAD, RequestMethod.DELETE, RequestMethod.GET})
//    public void uplaod(HttpServletRequest request, HttpServletResponse response) {
//        tusFileUploadResolver.upload(request, response);
//    }




    //SpEL来表示 :.+ 带上.的
    //嵌套的目录文件呢

    ///  @GetMapping("/downloadFile/{fileName:.+}")
    /*
    public ResponseEntity<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request) {
        // Load file as Resource
        Resource resource = fileStorageService.loadFileAsResource(fileName);


  */
    /** 带有 URI 模板

    @GetMapping(value = "/{id}/file-treeTest") // 交易信息编码
    public String getFileTree(@RequestParam(name = "id") String finTradeCode)
    {
        System.out.println("--> " + finTradeCode);
        return "/examples/targets/test2";
    }

    @ResponseBody
    @RequestMapping(method=RequestMethod.GET ,value="/abcTest/**")
    public String dubboMock(HttpServletResponse response, HttpServletRequest request){
        String url = request.getRequestURI();
        System.out.println("--> " + url);
        return "/examples/targets/test2";
    }
    */
 /*
    @RequestMapping(method=RequestMethod.GET ,value="/fileTest/**")
    public ResponseEntity<Resource>  downloadFile(HttpServletResponse response, HttpServletRequest request){
        String filePath;
        try {
            request.setCharacterEncoding("UTF-8");
          //剔除前面 /file/ 后的；
            filePath = request.getRequestURI();

            filePath =new String (filePath.getBytes("iso8859-1"),"utf-8");
        } catch (Exception ex) {
            throw new MyFileNotFoundException("Could not utf-8.", ex);
        }
        filePath = filePath.substring(6);
        //System.out.println("lujing==" + filePath);
        return downloadFile(filePath,request);
    }
 */

    //直接根据文件系统路径名来下载的模式：
    //用于支持中文的名字， 中间子路径也可支持中文的。
   /// @GetMapping("/file/**/{fileName}")
   //  public ResponseEntity<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request)




    //不考虑该文件已经被引用的情况时。
    //立刻删除刚刚上传的文件 ID;
    @PostMapping(value = "files/{id}/delete")
    public UploadFileResponse revertUploadFile(@PathVariable String id, @RequestParam("fileName") String fileName) {
        //String fileName = fileStorageService.storeFile(file);
        //todo:删除 上传的对象？？：｛没地方引用的文件对象可删除文件系统的对应文件｝
        return new UploadFileResponse(fileName, id,
                "成功剔除", 0);
    }


//    @ApiOperation(value = "查看存储bucket是否存在")
    @GetMapping("/bucketExists")
    public UploadFileResponse bucketExists(@RequestParam("bucketName") String bucketName) {
        return null;// R.ok().put("bucketName",minioUtil.bucketExists(bucketName));
    }

//    @ApiOperation(value = "创建存储bucket")
    @GetMapping("/makeBucket")
    public UploadFileResponse makeBucket(@RequestParam("fileName") String bucketName) {
        minioUtil.makeBucket(bucketName);
        return null;// R.ok().put("bucketName",minioUtil.makeBucket(bucketName));
    }

//    @ApiOperation(value = "删除存储bucket")
    @GetMapping("/removeBucket")
    public UploadFileResponse removeBucket(String bucketName) {
        return null;// R.ok().put("bucketName",minioUtil.removeBucket(bucketName));
    }
    @GetMapping("/bucketPolicy")
    public UploadFileResponse bucketPolicy(@RequestParam("fileName") String bucketName) {
        minioUtil.bucketPolicy(bucketName);
        return null;// R.ok().put("bucketName",minioUtil.makeBucket(bucketName));
    }
//    @ApiOperation(value = "获取全部bucket")
    @GetMapping("/getAllBuckets")
    public UploadFileResponse getAllBuckets() {
        List<Bucket> allBuckets = minioUtil.getAllBuckets();
        return null;// R.ok().put("allBuckets",allBuckets);
    }

//    @ApiOperation(value = "图片/视频预览")
    @GetMapping("/preview")
    public UploadFileResponse preview(@RequestParam("fileName") String fileName) {
        return new UploadFileResponse(fileName, minioUtil.preview(fileName),
                "preview", 0); // R.ok().put("filleName",minioUtil.preview(fileName));
    }

//    @ApiOperation(value = "文件下载")
    @GetMapping("/download")
    public UploadFileResponse download(@RequestParam("fileName") String fileName, HttpServletResponse res) {
//        minioUtil.download(fileName,res);
        return null;// R.ok();
    }
    @GetMapping("/testMinIO")
    public UploadFileResponse testMinIO(@RequestParam("fileName") String fileName, HttpServletResponse res) {
        Map<String, String> metas=minioUtil.getRetention(fileName);
        return null;
    }

    /** 上传文件 :另外可能做法的；
     * @param bucket
     * @param file
     * @param reqObjectId 对象ID，如果不指定，自动生成
     * @return 对象ID
     * @throws IOException
     */
    @PostMapping("/uploadMinIO")
    @ResponseStatus(HttpStatus.CREATED)
    public String put(@PathVariable("bucket") String bucket, @RequestParam("file") MultipartFile file,
                      @RequestParam(value = "objectId", required = false) String reqObjectId) throws IOException {
        if (file.isEmpty()) {
            return null;//  throw new FileEmptyException();
        }
        String fileName = file.getOriginalFilename();
        if (!StringUtils.hasText(fileName)) {
            return null;//  throw new FileNameException();
        }
        fileName = StringUtils.cleanPath(fileName);
//        final String objectId = reqObjectId == null ? String.valueOf(Snowflake.nextId()) : reqObjectId;
//        final String contentType = tika.detect(file.getInputStream());  //用Apache Tika进行文件类型检测 tika-core：
//        final String objectName = Helper.objectName(objectId);
//        final UserData userData = new UserData(fileName, SecurityUtils.getCurrentUser(), objectId);
//【函数式编程】例子 ： 类似对void putObject(final MinioUserMetadata metadata, final InputStream file, final Consumer<PutObjectArgs.Builder> consumer) { consumer.accept(builder);}@
//      ?minioUtil?.minioClient.putObject(bucket, objectName, file.getInputStream(),
//                builder -> builder.contentType(contentType).userMetadata(userData.toMap()));
        return "";//objectId;
    }
}


//@RequestParam @RequestBody @PathVariable 等参数绑定注解详解 https://www.cnblogs.com/guoyinli/p/7056146.html
